package cc.rengu.redp.system.service.impl;

import cc.rengu.redp.common.domain.RedpResponse;
import cc.rengu.redp.common.exception.RedpException;
import cc.rengu.redp.common.properties.RedpProperties;
import cc.rengu.redp.common.utils.DateUtil;
import cc.rengu.redp.common.utils.SpringContextUtil;
import cc.rengu.redp.system.domain.FileCharacter;
import cc.rengu.redp.system.service.FileManageService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.springframework.stereotype.Service;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

@Slf4j
@Service
public class FileManageServiceImpl implements FileManageService {

    private final static String BASE_FILE_PATH = SpringContextUtil.getBean(RedpProperties.class).getBaseFilePath();

    @Override
    public List<FileCharacter> getFileList(String currPath) {
        //创建集合
        List<FileCharacter> fileCharacterList = new ArrayList<>();
        //根据目录创建file对象
        File file = new File(Paths.get(BASE_FILE_PATH, currPath).toString());

        File[] files = file.listFiles();
        for (int i = 0; i < files.length; i++) {
            FileCharacter fileCharacter = new FileCharacter();
            if (files[i].isFile()) {
                //文件
                fileCharacter.setIsDir(false);
                //文件的大小
                fileCharacter.setFileSize(String.valueOf(files[i].length()));
            } else {
                //目录
                fileCharacter.setIsDir(true);
            }
            //名称
            fileCharacter.setName(files[i].getName());
            //基于基本路径的相对路径
            fileCharacter.setFullName(files[i].getAbsolutePath().replace(BASE_FILE_PATH, ""));
            //文件的创建时间
            fileCharacter.setUpdateTime(DateUtil.longToLocalDateTime(files[i].lastModified()));
            try {
                //文件的创建时间
                long createTime = Files.readAttributes(files[i].toPath(), BasicFileAttributes.class).creationTime().toMillis();
                fileCharacter.setCreateTime(DateUtil.longToLocalDateTime(createTime));
            } catch (IOException e) {
                log.error("get file createTime error.", e);
            }

            fileCharacterList.add(fileCharacter);
        }

        //文件夹优先
        fileCharacterList.sort(Comparator.comparing(FileCharacter::getIsDir).reversed());

        return fileCharacterList;
    }

    @Override
    public RedpResponse createDirectory(String currPath, String directoryName) {
        File file = new File(Paths.get(BASE_FILE_PATH, currPath, directoryName).toString());
        if (!file.exists()) {
            boolean rs = file.mkdir();
            if (rs) {
                return RedpResponse.getInstance().success().message("文件夹创建成功");
            } else {
                return RedpResponse.getInstance().failure().message("文件夹创建失败");

            }
        } else {
            return RedpResponse.getInstance().failure().message("文件夹已存在");
        }
    }

    @Override
    public RedpResponse deleteFileOrDirectory(List<String> fullNames) {
        int successNum = 0;
        for (String fn : fullNames) {
            File file = new File(Paths.get(BASE_FILE_PATH, fn).toString());
            if (FileUtils.deleteQuietly(file)) {
                successNum++;
            }
        }

        if (successNum == fullNames.size()) {
            return RedpResponse.getInstance().success().message("删除文件（夹）成功");
        } else if (successNum > 0 && successNum < fullNames.size()) {
            return RedpResponse.getInstance().failure().message("部分文件（夹）删除失败");
        } else {
            return RedpResponse.getInstance().failure().message("删除失败");
        }
    }

    @Override
    public RedpResponse deleteFileOrDirectory(String fullName) {
        File file = new File(Paths.get(BASE_FILE_PATH, fullName).toString());
        if (FileUtils.deleteQuietly(file)) {
            return RedpResponse.getInstance().failure().message("删除失败");
        } else {
            return RedpResponse.getInstance().success().message("删除文件（夹）成功");
        }
    }

    @Override
    public RedpResponse renameFileOrDirectory(String fullName, String targetName) {
        File oldName = new File(Paths.get(BASE_FILE_PATH, fullName).toString());
        // 新的文件或目录
        File newName = new File(oldName.getParent(), targetName);
        if (newName.exists()) {
            return RedpResponse.getInstance().failure().message("已存在名称相同的文件");
        }

        if (oldName.exists()) {
            if (oldName.renameTo(newName)) {
                return RedpResponse.getInstance().success().message("重命名成功");
            } else {
                return RedpResponse.getInstance().failure().message("重命名失败");
            }
        } else {
            return RedpResponse.getInstance().failure().message("源文件不存在");
        }
    }

    @Override
    public RedpResponse moveFileOrDirectory(List<String> fullNames, String targetPath) {
        File targetFile = new File(Paths.get(BASE_FILE_PATH, targetPath).toString());
        if (!targetFile.isDirectory() || !targetFile.exists()) {
            return RedpResponse.getInstance().failure().message("目标路径不可用");
        }

        int successNum = 0;

        for (String fn : fullNames) {
            File srcFile = new File(Paths.get(BASE_FILE_PATH, fn).toString());
            if (srcFile.exists()) {
                try {
                    if (srcFile.isDirectory()) {
                        FileUtils.moveDirectoryToDirectory(srcFile, targetFile, false);
                    } else {
                        FileUtils.moveFileToDirectory(srcFile, targetFile, false);
                    }
                } catch (IOException e) {
                    log.error("moveDirectoryToDirectory error", e);
                    continue;
                }

                successNum++;
            }
        }

        if (successNum == fullNames.size()) {
            return RedpResponse.getInstance().success().message("移动成功");
        } else if (successNum > 0 && successNum < fullNames.size()) {
            return RedpResponse.getInstance().failure().message("部分文件（夹）移动失败");
        } else {
            return RedpResponse.getInstance().failure().message("移动失败");
        }
    }

    @Override
    public String getSimpleFileName(String fullName) {
        File file = new File(Paths.get(BASE_FILE_PATH, fullName).toString());
        if (file.exists()) {
            return file.getName();
        }

        return null;
    }

    @Override
    public void downloadFile(String fullName, OutputStream outputStream) throws RedpException {
        File file = new File(Paths.get(BASE_FILE_PATH, fullName).toString());
        InputStream is = null;
        OutputStream os = null;
        try {
            is = new BufferedInputStream(new FileInputStream(file));
            byte[] buffer = new byte[is.available()];
            is.read(buffer);
            is.close();
            os = new BufferedOutputStream(outputStream);
            os.write(buffer);
            os.flush();
            os.close();
        } catch (IOException e) {
            log.error("download file error", e);
            throw new RedpException(e.getMessage());
        } finally {
            try {
                if (is != null) {
                    is.close();
                }
                if (os != null) {
                    os.close();
                }
            } catch (IOException e) {
                log.error("is/os close error", e);
                throw new RedpException(e.getMessage());
            }
        }
    }

    @Override
    public void uploadFile(String fullName, InputStream inputStream, boolean allowRewrite) throws RedpException {
        File file = new File(Paths.get(BASE_FILE_PATH, fullName).toString());
        OutputStream os = null;
        InputStream is = null;
        if (file.exists() && !allowRewrite) {
            throw new RedpException("文件已存在");
        }
        try {
            os = new BufferedOutputStream(new FileOutputStream(file));
            is = new BufferedInputStream(inputStream);
            byte[] buffer = new byte[is.available()];
            is.read(buffer);
            is.close();
            os.write(buffer);
            os.flush();
            os.close();
        } catch (IOException e) {
            log.error("upload file error", e);
            throw new RedpException(e.getMessage());
        } finally {
            try {
                if (is != null) {
                    is.close();
                }
                if (os != null) {
                    os.close();
                }
            } catch (IOException e) {
                log.error("is/os close error", e);
                throw new RedpException(e.getMessage());
            }
        }
    }

    @Override
    public FileCharacter getFileCharacter(String fullName) {
        File file = new File(Paths.get(BASE_FILE_PATH, fullName).toString());
        if (file.exists()) {
            FileCharacter fileCharacter = new FileCharacter();
            if (file.isFile()) {
                //文件
                fileCharacter.setIsDir(false);
                //文件的大小
                fileCharacter.setFileSize(String.valueOf(file.length()));
            } else {
                //目录
                fileCharacter.setIsDir(true);
            }
            //名称
            fileCharacter.setName(file.getName());
            //基于基本路径的相对路径
            fileCharacter.setFullName(file.getAbsolutePath().replace(BASE_FILE_PATH, ""));
            //文件的创建时间
            fileCharacter.setUpdateTime(DateUtil.longToLocalDateTime(file.lastModified()));
            try {
                //文件的创建时间
                long createTime = Files.readAttributes(file.toPath(), BasicFileAttributes.class).creationTime().toMillis();
                fileCharacter.setCreateTime(DateUtil.longToLocalDateTime(createTime));
            } catch (IOException e) {
                log.error("get file createTime error.", e);
                return null;
            }
        } else {
            log.error("文件{}不存在", fullName);
            return null;
        }

        return null;
    }
}
